package aglo_01;

import java.util.Arrays;

public class Test4 {
	/**
	 *归并排序
	 *先排序，再合并；中间有个拆分过程
	 * @param arr
	 */
	public static void sort(int[] arr){
		if (arr == null || arr.length < 2) {	//一定要加这个不然空数组会报错，坑了我20min
			return;
		}
		mergeSort(arr,0,arr.length-1);
	}
	private static void mergeSort(int[] arr, int start, int end) {
		if(start==end){
			return;
		}
		//拆分
		int mid=(end+start)/2;
		mergeSort(arr, start, mid);
		mergeSort(arr, mid+1, end);
		//合并
		merge(arr,start,end,mid);
	}
	private static void merge(int[] arr, int start, int end, int mid) {
		//此时两个数组以mid分隔，都是有序数组
		//通过一个中间数组来帮助合并过程
		int[] help=new int[end-start+1];
		//设置两个数组指针都指向左侧最小值，哪个小移动哪个
		int p1=start;
		int p2=mid+1;
		int i = 0;
		//当某个数组指针移动完毕结束比较
		while(p1<=mid&&p2<=end){
			help[i++]=arr[p1]<arr[p2]?arr[p1++]:arr[p2++];
		}
		//如果左侧数组有多余数
		while(p1<=mid){
			help[i++]=arr[p1++];
		}
//		如果右侧数组有多余数
		while(p2<=end){
			help[i++]=arr[p2++];
		}
		//将中间数组赋值到原数组
		for (int j = 0; j < help.length; j++) {
			arr[start++]=help[j];
		}
		
		//其实也可以不借助中间数组，要麻烦一点
	}
	// for test
		public static void comparator(int[] arr) {
			Arrays.sort(arr);
		}

		// for test
		public static int[] generateRandomArray(int maxSize, int maxValue) {
			int[] arr = new int[(int) ((maxSize + 1) * Math.random())];
			for (int i = 0; i < arr.length; i++) {
				arr[i] = (int) ((maxValue + 1) * Math.random()) - (int) (maxValue * Math.random());
			}
			return arr;
		}

		// for test
		public static int[] copyArray(int[] arr) {
			if (arr == null) {
				return null;
			}
			int[] res = new int[arr.length];
			for (int i = 0; i < arr.length; i++) {
				res[i] = arr[i];
			}
			return res;
		}

		// for test
		public static boolean isEqual(int[] arr1, int[] arr2) {
			if ((arr1 == null && arr2 != null) || (arr1 != null && arr2 == null)) {
				return false;
			}
			if (arr1 == null && arr2 == null) {
				return true;
			}
			if (arr1.length != arr2.length) {
				return false;
			}
			for (int i = 0; i < arr1.length; i++) {
				if (arr1[i] != arr2[i]) {
					return false;
				}
			}
			return true;
		}

		// for test
		public static void printArray(int[] arr) {
			if (arr == null) {
				return;
			}
			for (int i = 0; i < arr.length; i++) {
				System.out.print(arr[i] + " ");
			}
			System.out.println();
		}

		// for test
		public static void main(String[] args) {
			int testTime = 500000;
			int maxSize = 100;
			int maxValue = 100;
			boolean succeed = true;
			for (int i = 0; i < testTime; i++) {
				int[] arr1 = generateRandomArray(maxSize, maxValue);
				int[] arr2 = copyArray(arr1);
				sort(arr1);
				comparator(arr2);
				if (!isEqual(arr1, arr2)) {
					succeed = false;
					break;
				}
			}
			System.out.println(succeed ? "Nice!" : "Fucking fucked!");

			int[] arr = generateRandomArray(maxSize, maxValue);
			printArray(arr);
			sort(arr);
			printArray(arr);
		}
}
